#pragma once

#include <string>
#include <array>

namespace BasicTemplate
{
    /**
     * 10、基本模板的术语
     * 10.1.“类模板”还是“模板类”
     *      尽量使用 xxx模板 来指定这是一个模板，而少用 模板xxx（这种方式指定的范围不仅仅是模板）。
     * 10.2.替换、实例化和特化
     *      模板实例化：通过替换模板的具体参数，为模板中的常规类、类型别名、函数、成员函数或变量实际创建定义的过程。
     *          部分实例化：使用的部分实例化或声明的实例化。
     *      特化：由 实例化 或 不完全实例化 (即类、函数、成员函数或变量) 产生的实体。
     *      显式特化（替代机制）：允许开发者显式地指定与模板参数的特殊替换绑定的声明，通常通过前缀 template<> 引入。对应实例化
     *      偏特化：仍有模板参数的特化，对应不完全实例化
     * 10.3.声明和定义  如何处理模板中不完整类型的提示，参考11.5节
     * 10.4.唯一定义原则
     * 10.5.模板实参与模板形参
     *      模板参数是那些列在模板声明或定义中的关键字 Template 之后的参数 (示例中是 T 和 N)
     *      模板实参是替代模板形参的项 (示例中是 double 和 10)。与模板形参不同，模板实参可以不仅仅是“名称”。
     */

    /**
     * 2.替换、实例化和特化（感觉这部分有点混乱）
     * 个人理解：
     * 实例化指的是： 类模板->具体类、函数模板->具体函数 的过程，也就是显式特化
     * 部分实例化指的是：模板中的部分参数被实例化，而部分没有，也就是偏特化
     */
    template <typename T1, typename T2> // primary class template (主模板、通用模板)
    class MyClass
    {
    };

    template <>
    class MyClass<int, float> // explicit specialization (显式特化(实例化))
    {
    };

    template <typename T> // partial specialization (偏特化(部分实例化))
    class MyClass<std::string, T>
    {
    };

    template <typename T> // partial specialization (偏特化)
    class MyClass<T, T>
    {
    };

    /**
     * 5、模板实参与模板形参
     *      模板参数是那些列在模板声明或定义中的关键字 Template 之后的参数 (示例中是 T 和 N)
     *      模板实参是替代模板形参的项 (示例中是 double 和 10)。与模板形参不同，模板实参可以不仅仅是“名称”。
     */
    // 一种T既是模板形参也是模板实参的情况
    template <typename T> // 模板形参
    class ArrayInClass
    {
    private:
        std::array<T, 12> m_array; // 模板实参
    };

};